import type { AtLeast, IRoom } from '@rocket.chat/core-typings';
import { isRoomFederated } from '@rocket.chat/core-typings';
import type { SubscriptionWithRoom } from '@rocket.chat/ui-contexts';

import { getAvatarURL } from '../../../../app/utils/client/getAvatarURL';
import { getUserAvatarURL } from '../../../../app/utils/client/getUserAvatarURL';
import type { IRoomTypeClientDirectives } from '../../../../definition/IRoomTypeConfig';
import { RoomSettingsEnum, RoomMemberActions, UiTextContext } from '../../../../definition/IRoomTypeConfig';
import { getDirectMessageRoomType } from '../../../../lib/rooms/roomTypes/direct';
import { Users, Rooms, Subscriptions } from '../../../stores';
import * as Federation from '../../federation/Federation';
import { settings } from '../../settings';
import { roomCoordinator } from '../roomCoordinator';

export const DirectMessageRoomType = getDirectMessageRoomType(roomCoordinator);

roomCoordinator.add(
	{
		...DirectMessageRoomType,
		label: 'Direct_Messages',
	},
	{
		allowRoomSettingChange(_room, setting) {
			if (isRoomFederated(_room as IRoom)) {
				return Federation.isRoomSettingAllowed(_room, setting);
			}
			switch (setting) {
				case RoomSettingsEnum.TYPE:
				case RoomSettingsEnum.NAME:
				case RoomSettingsEnum.SYSTEM_MESSAGES:
				case RoomSettingsEnum.DESCRIPTION:
				case RoomSettingsEnum.READ_ONLY:
				case RoomSettingsEnum.REACT_WHEN_READ_ONLY:
				case RoomSettingsEnum.ARCHIVE_OR_UNARCHIVE:
				case RoomSettingsEnum.JOIN_CODE:
					return false;
				case RoomSettingsEnum.E2E:
					return settings.watch('E2E_Enable') === true;
				default:
					return true;
			}
		},

		allowMemberAction(room, action, showingUserId, userSubscription) {
			if (isRoomFederated(room as IRoom)) {
				return Federation.actionAllowed(room, action, showingUserId, userSubscription);
			}
			switch (action) {
				case RoomMemberActions.BLOCK:
					return !this.isGroupChat(room);
				default:
					return false;
			}
		},

		roomName(roomData) {
			const subscription = ((): { fname?: string; name?: string } | undefined => {
				if (roomData.fname || roomData.name) {
					return {
						fname: roomData.fname,
						name: roomData.name,
					};
				}

				if (!roomData._id) {
					return undefined;
				}

				return Subscriptions.state.find((record) => record.rid === roomData._id);
			})();

			if (!subscription) {
				return;
			}

			if (settings.watch('UI_Use_Real_Name') && subscription.fname) {
				return subscription.fname;
			}

			return subscription.name;
		},

		isGroupChat(room) {
			return (room?.uids?.length || 0) > 2;
		},

		getUiText(context) {
			switch (context) {
				case UiTextContext.HIDE_WARNING:
					return 'Hide_Private_Warning';
				case UiTextContext.LEAVE_WARNING:
					return 'Leave_Private_Warning';
				default:
					return '';
			}
		},

		getAvatarPath(room) {
			if (!room) {
				return '';
			}

			// if coming from sidenav search
			if (room.name && room.avatarETag) {
				return getUserAvatarURL(room.name, room.avatarETag);
			}

			if (this.isGroupChat(room)) {
				return getAvatarURL({
					username: (room.uids || []).length + (room.usernames || []).join(),
					cache: room.avatarETag,
				}) as string;
			}

			const subscriptionName = Subscriptions.state.find((record) => record.rid === room._id)?.name;
			if (subscriptionName) {
				const { username, avatarETag } = Users.state.find((record) => record.username === subscriptionName) || {};
				return getUserAvatarURL(username || subscriptionName, avatarETag);
			}

			return getUserAvatarURL(room.name || this.roomName(room) || '');
		},

		getIcon(room) {
			if (isRoomFederated(room)) {
				return 'globe';
			}

			if (this.isGroupChat(room)) {
				return 'balloon';
			}

			return 'at';
		},

		extractOpenRoomParams({ rid }) {
			return { type: 'd', reference: rid };
		},

		findRoom(identifier) {
			const predicate = (record: SubscriptionWithRoom) => record.t === 'd' && (record.name === identifier || record.rid === identifier);

			const subscription = Subscriptions.state.find(predicate);
			if (subscription?.rid) {
				return Rooms.state.get(subscription.rid);
			}
		},
	} as AtLeast<IRoomTypeClientDirectives, 'isGroupChat' | 'roomName'>,
);
